package {
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Spritemap;
	import net.flashpunk.graphics.Tilemap;
	import net.flashpunk.utils.Input;
	import net.flashpunk.utils.Key;
	
	/**
	 * ...
	 * @author Guido
	 */
	public class Block extends Entity {
		private var fixed:Boolean;
		private var number:int;
		private var posibilities:ArrayWrapper;
		private var posibleMode:Boolean;
		
		[Embed(source='assets/sheet.png')]
		private const NUMBERS:Class;
		private var numberSprite:Spritemap;
		
		[Embed(source='assets/posibilities-sheet.png')]
		private const POSIBILITIES:Class;
		private var posibleTiles:Tilemap;
		
		public function Block(x:int, y:int, allPosible:Boolean = false){
			fixed = false;
			number = 0;
			posibilities = new ArrayWrapper(9);
			for (var i:int = 1; i < 10; i++){
				posibilities.put(i, allPosible);
			}
			this.x = x;
			this.y = y;
			width = Const.BLOCK_WIDTH;
			height = Const.BLOCK_HEIGHT;
			setHitbox(width, height);
			numberSprite = new Spritemap(NUMBERS, 23, 30);
			posibleTiles = new Tilemap(POSIBILITIES, width, height, 17, 17);
			setPosibleMode(false);
			type = "block";
			SudokuDemonstration.world.add(this);
		}
		
		public function getNumber():int {
			return number;
		}
		
		public function setNumber(n:int):void {
			if ((n < 1) || (n > 9)){
				throw new Error("Se intentó asignar un número fuera de rango");
			} else {
				numberSprite.setFrame(n - 1);
				this.number = n;
			}
		}
		
		public function removeNumber():void {
			this.number = 0;
		}
		
		public function fixNumber():void {
			fixed = true;
		}
		
		public function assignRandomPosibility():int {
			//TODO
			return 1;
		}
		
		public function receiveInput():void {
			if (!fixed) {
				if (Input.pressed(Key.SPACE)) {
					setPosibleMode(!posibleMode);
				}
				
				if (Input.pressed(Key.DIGIT_1)){
					changeNumber(1);
				}
				if (Input.pressed(Key.DIGIT_2)){
					changeNumber(2);
				}
				if (Input.pressed(Key.DIGIT_3)){
					changeNumber(3);
				}
				if (Input.pressed(Key.DIGIT_4)){
					changeNumber(4);
				}
				if (Input.pressed(Key.DIGIT_5)){
					changeNumber(5);
				}
				if (Input.pressed(Key.DIGIT_6)){
					changeNumber(6);
				}
				if (Input.pressed(Key.DIGIT_7)){
					changeNumber(7);
				}
				if (Input.pressed(Key.DIGIT_8)){
					changeNumber(8);
				}
				if (Input.pressed(Key.DIGIT_9)){
					changeNumber(9);
				}
			}
		}
		
		/* Cambia el número dependiendo del estado, si esta en posibleMode
		 * agrega o quita el numero, sino, pone el numero definitivo */ 
		public function changeNumber(n : int) {
			if (posibleMode) {
				if (posibilities.get(n))
					removePosibility(n);
				else
					addPosibility(n);
			}
			else 
				setNumber(n);
		}
		
		public function addPosibility(n:int):void {
			posibilities.put(n, true);
			showPosibility(n);
		}
		
		public function removePosibility(n:int):void {
			posibilities.put(n, false);
			hidePosibility(n);
		}
		
		public function setPosibleMode(posible : Boolean):void {
			if (posible) {
				graphic = posibleTiles;
				posibleMode = true;
			}
			else {
				graphic = numberSprite;
				posibleMode = false;
			}
		}
		
		public function showNumber():void {
			graphic = numberSprite;
		}
		
		private function showPosibility(n:int):void {
			var row:int = (n - 1) / 3;
			var col:int = (n - 1) % 3;
			posibleTiles.setRect(col, row, 1, 1, n);
		}
		
		private function hidePosibility(n:int):void {
			var row:int = (n - 1) / 3;
			var col:int = (n - 1) % 3;
			posibleTiles.setRect(col, row, 1, 1, 0);
		}
		
		private function togglePosibility(n : int) : void {
			var row:int = (n - 1) / 3;
			var col:int = (n - 1) % 3;
			var tile : int;
			if (posibilities.get(n)) 
				tile = 0;
			else 
				tile = n;
			
			posibleTiles.setRect(col, row, 1, 1, 0);
		}
		
	}
	
}